<?php

namespace App\Http\Controllers\Export;

use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;

/**
 * 导出excel
 * 
 * composer require maatwebsite/excel
 */
class Export implements FromCollection, WithHeadings, WithEvents
{
    protected $data;
    protected $headings;
    protected $columnWidth = []; //设置列宽       key：列  value:宽
    protected $rowHeight = [];  //设置行高       key：行  value:高
    protected $rowHeightNumber = 1;  //设置行高数量 
    protected $mergeCells = []; //合并单元格    value:A1:K8

    // protected $mergeCellsArray = []; //合并单元格数据，里面包含2个元素 start_index end_index
    // protected $mergeCellsNumber = 2; //合并单元格数据，个数
    protected $font = [];       //设置字体       key：A1:K8  value:Arial
    protected $fontSize = [];       //设置字体大小       key：A1:K8  value:11
    protected $bold = [];       //设置粗体       key：A1:K8  value:true
    protected $background = []; //设置背景颜色    key：A1:K8  value:#F0F0F0F
    protected $vertical = [];   //设置定位       key：A1:K8  value:center
    protected $sheetName; //sheet title
    protected $borders = []; //设置边框颜色  key：A1:K8  value:#000000
    protected $wrapText = [];   //设置是否自动换行 key：A1:K8  value:bool
    protected $freezePane = 'A2'; //冻结排  A2为第一排  冻结下面的，前面的跟着一起被冻结

    protected $excelImg = []; //图片数组
    protected $imgPosition = ''; //图片出现的列  A、B、C
    protected $imgWidth = 10; //图片宽
    protected $imgHeight = 10; //图片高

    //设置页面属性时如果无效   更改excel格式尝试即可

    //构造函数传值
    public function __construct($data, $headings, $sheetName)
    {
        $this->data = $data;
        $this->headings = $headings;
        $this->sheetName = $sheetName;
        $this->createData();
    }


    //导出图片设置
    // public function drawings()
    // {
    //     //这里的数据自己组装
    //     $draw_arr = [1 =>'uploads/default/default_activity.png', 2 => 'uploads/default/default_lib_book.png'];
    //     $result = [];
    //     foreach ($draw_arr as $k => $v) {
    //         $k +=1;
    //       ${'drawing'.$k} = new Drawing();
    //       ${'drawing'.$k}->setName('图片');
    //       ${'drawing'.$k}->setDescription('这是图片');
    //       //图片路径
    //       ${'drawing'.$k}->setPath(public_path($v));
    //       ${'drawing'.$k}->setHeight(50);
    //       //设置图片列
    //       ${'drawing'.$k}->setCoordinates('G'.$k);
    //       $result[] = ${'drawing'.$k};
    //     }
    //     //dump($result);die;
    //     return $result;
    // }

    public function headings(): array
    {
        return $this->headings;
    }

    //数组转集合
    public function collection()
    {
        return new Collection($this->data);
    }
    //业务代码
    public function createData()
    {
        $this->data = collect($this->data)->toArray();
    }

    public function registerEvents(): array
    {
        return [
            AfterSheet::class  => function (AfterSheet $event) {
                //设置sheet页名称  (可以不要，系统自动调用)
                // $event->getSheet()->getDelegate()->setTitle($this->sheetName);

                //设置区域单元格垂直居中
                $event->sheet->getDelegate()->getStyle('A1:Z1265')->getAlignment()->setVertical('center');
                //设置区域单元格水平居中
                $event->sheet->getDelegate()->getStyle('A1:Z1265')->getAlignment()->setHorizontal('center');
                //设置列宽
                foreach ($this->columnWidth as $column => $width) {
                    $event->sheet->getDelegate()
                        ->getColumnDimension($column)
                        ->setWidth($width);
                }
                //设置行高，$i为数据行数
                if (is_array($this->rowHeight)) {
                    //数组形式
                    foreach ($this->rowHeight as $row => $height) {
                        $event->sheet->getDelegate()
                            ->getRowDimension($row)
                            ->setRowHeight($height);
                    }
                } else {
                    //数字形式
                    for ($i = 1; $i <= $this->rowHeightNumber; $i++) {
                        $event->sheet->getDelegate()
                            ->getRowDimension($i)
                            ->setRowHeight($this->rowHeight);
                    }
                }

                //设置区域单元格垂直居中
                foreach ($this->vertical as $region => $position) {
                    $event->sheet->getDelegate()
                        ->getStyle($region)
                        ->getAlignment()
                        ->setVertical($position);
                }

                //设置区域单元格字体
                foreach ($this->font as $region => $value) {
                    $event->sheet->getDelegate()
                        ->getStyle($region)
                        ->getFont()->setName($value);
                }
                //设置区域单元格字体大小
                foreach ($this->fontSize as $region => $value) {
                    $event->sheet->getDelegate()
                        ->getStyle($region)
                        ->getFont()
                        ->setSize($value);
                }

                //设置区域单元格字体粗体
                foreach ($this->bold as $region => $bool) {
                    $event->sheet->getDelegate()
                        ->getStyle($region)
                        ->getFont()
                        ->setBold($bool);
                }


                //设置区域单元格背景颜色
                foreach ($this->background as $region => $item) {
                    $event->sheet->getDelegate()->getStyle($region)->applyFromArray([
                        'fill' => [
                            'fillType' => 'linear', //线性填充，类似渐变
                            'startColor' => [
                                'rgb' => $item //初始颜色
                            ],
                            //结束颜色，如果需要单一背景色，请和初始颜色保持一致
                            'endColor' => [
                                'argb' => $item
                            ]
                        ]
                    ]);
                }
                //设置边框颜色
                foreach ($this->borders as $region => $item) {
                    $event->sheet->getDelegate()->getStyle($region)->applyFromArray([
                        'borders' => [
                            'allBorders' => [
                                'borderStyle' => Border::BORDER_THIN,
                                'color' => ['argb' => $item],
                            ],
                        ],
                    ]);
                }

                //合并单元格 1
                 $event->sheet->getDelegate()->setMergeCells($this->mergeCells);

                //合并单元格 2
                // foreach ($this->mergeCellsArray as $key => $val) {
                //     //5为合并行数
                //     for ($i = 1; $i <= $this->mergeCellsNumber; $i++) {
                //         $event->sheet->getDelegate()->setMergeCells(decimal_to_letter($i) . $val['start_index'] . ':' . decimal_to_letter($i) . $val['end_index']);
                //     }
                // }

                if (!empty($this->sheetName)) {
                    $event->sheet->getDelegate()->setTitle($this->sheetName);
                }


                //设置自动换行
                foreach ($this->wrapText as $column => $bool) {
                    $event->sheet->getDelegate()
                        ->getStyle($column)
                        ->getAlignment()
                        ->setWrapText(true);
                }

                if ($this->freezePane) {
                    //  foreach ($this->freezePane as $region => $row) {
                    $event->sheet->freezePane($this->freezePane); //冻结第一排 为 A2
                    // }
                }

                foreach ($this->excelImg as $key => $val) {
                    $number = $key + 2;
                    //图片需要单独定义一个数组，然后循环处理         //E2时表格横E竖2，图片需要出现的位置
                    $img = $val ? 'uploads/' . $val : null; //有图片直接写地址路径，系统会自动拼接到 public目录，没有文件直接写null
                    $this->setImage2Excel($event, $this->imgPosition . $number, $img, $this->imgWidth, $this->imgHeight, $key);
                }
            }
        ];
    }

    /**
     * 添加图片到excel
     * @param $event
     * @param $position：excel表位置
     * @param $path：图片路径
     * @param $width：图片宽度
     * @param $height：图片高度
     * @throws \PhpOffice\PhpSpreadsheet\Exception
     */
    private function setImage2Excel($event, $position, $path, $width, $height, $key)
    {
        if (empty($path)) {
            return false;
        }
        $drawing = new Drawing();
        $drawing->setName('Logo');
        $drawing->setDescription('Logo');
        $drawing->setCoordinates($position);
        $drawing->setPath(public_path($path));
        ($width == 0) ? null : $drawing->setWidth($width);
        ($height == 0) ? null : $drawing->setHeight($height);
        $drawing->setWorksheet($event->sheet->getDelegate());
    }

    /**
     * @return array
     * @2020/3/22 10:33
     * [
     *    A1:K7 => true
     * ]
     */
    public function setWrapText(array $wrapText)
    {
        $this->wrapText = array_change_key_case($this->symbol($wrapText), CASE_UPPER);
    }

    /**
     * @return array
     * [
     *    'B' => 40,
     *    'C' => 60
     * ]
     */
    public function setColumnWidth(array $columnwidth)
    {
        $this->columnWidth = array_change_key_case($columnwidth, CASE_UPPER);
    }

    /**
     * @return mixed
     * [
     *    1 => 40,
     *    2 => 60
     * ]
     * $rowHeight  如果是数组形式，则使用数组数据进行分配，如果是 数字类型，则是代表每行的高度
     * $rowsNumber  列数，若rowHight 为 数值时有效
     * 
     */
    public function setRowHeight($rowHeight, $rowHeightNumber = 1)
    {
        $this->rowHeight = $rowHeight;
        $this->rowHeightNumber = $rowHeightNumber;
    }

    /**
     * @return array
     * [
     *    A1:K7 => '宋体'
     * ]
     */
    public function setFont(array $font)
    {
        $this->font = array_change_key_case($font, CASE_UPPER);
    }

    /**
     * @return array
     * @2020/3/22 10:33
     * [
     *    A1:K7 => true
     * ]
     */
    public function setBold(array $bold)
    {
        $this->bold = array_change_key_case($bold, CASE_UPPER);
    }

    /**
     * @return array
     * @2020/3/22 10:33
     * [
     *    A1:K7 => F0FF0F
     * ]
     */
    public function setBackground(array $background)
    {
        $this->background = array_change_key_case($background, CASE_UPPER);
    }
    /**
     * @return array
     * [
     *    A1:K7
     * ]
     */
    public function setMergeCells(array $mergeCells)
    {
        $this->mergeCells = array_change_key_case($mergeCells, CASE_UPPER);
    }
    /**
     * @return array
     * [
     *    A1:K7 => 14
     * ]
     */
    public function setFontSize(array $fontSize)
    {
        $this->fontSize = array_change_key_case($fontSize, CASE_UPPER);
    }
    /**
     * @return array
     * [
     *    A1:K7 => #000000
     * ]
     */
    public function setBorders(array $borders)
    {
        $this->borders = array_change_key_case($borders, CASE_UPPER);
    }

    /**
     * @return array 
     * 
     * A2 
     */
    public function setFreezePane(string $freezePane)
    {
        $this->freezePane = $freezePane;
    }

    /**
     * @return array 
     * 
     * $excelImg  图片数组，及时不存在，那一列的值也要存在，为空或null 
     * $position  图片出现的列  A 、B、C
     * $imgWidth  图片宽
     * $imgHeight  图片高
     */
    public function setExcelImg(array $excelImg, string $imgPosition, int $imgWidth = 10, int $imgHeight = 10)
    {
        $this->excelImg = $excelImg;
        $this->imgPosition = $imgPosition;
        $this->imgWidth = $imgWidth;
        $this->imgHeight = $imgHeight;
    }



    public function symbol($param)
    {
        $record = [];
        $count = count($this->data) + 1; //加上表头
        foreach ($param as $key => $value) {
            $str = str_replace("*", $count, $key);
            $record[$str] = $value;
        }
        return $record;
    }
}
